﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ConsoleAppThread
{
	public class MyMultiMap<Key, Value> : IDisposable, IEnumerable<KeyValuePair<Key, List<Value>>>
		where Key : IComparable<Key>
		where Value : IComparable<Value>
	{

		private Dictionary<Key, List<Value>> m_dictionary;
		bool disposing = false;

		private static object syncLock = new object();

		public MyMultiMap()
		{
			m_dictionary = new Dictionary<Key, List<Value>>();
		}

		public void Dispose()
		{
			Dispose(true);
		}

		private void Dispose(bool p)
		{
			lock (syncLock)
			{
				disposing = p;
				if (!disposing)
				{
					if (m_dictionary.Keys.Count > 0)
					{
						foreach (Key k in m_dictionary.Keys)
						{
							if (m_dictionary[k].Count > 0)
							{
								m_dictionary[k].Clear();
							}
						}
					}
					m_dictionary.Clear();

					if (disposing)
					{
						m_dictionary = null;
						syncLock = null;
						GC.SuppressFinalize(this);
						GC.Collect();
					}
				}

			}
		}

		public void ClearAll()
		{
			this.Dispose(false);
		}

		public void Add(Key key, Value val)
		{
			lock (syncLock)
			{
				if (m_dictionary.ContainsKey(key))
				{
					m_dictionary[key].Add(val);
				}
				else
				{
					List<Value> valData = new List<Value>();
					valData.Add(val);
					m_dictionary.Add(key, valData);
				}
			}
		}

		public void AddWithoutValue(Key key)
		{
			lock (syncLock)
			{
				if (m_dictionary.ContainsKey(key))
				{
					return;
				}
				else
				{
					List<Value> valData = new List<Value>();
					m_dictionary.Add(key, valData);
				}
			}
		}

		public int Count
		{
			get
			{
				lock (syncLock)
				{
					return m_dictionary.Count;
				}
			}
		}

		public List<Value> GetData(Key key)
		{
			lock (syncLock)
			{
				if (m_dictionary.ContainsKey(key))
				{
					return m_dictionary[key];
				}
			}
			return new List<Value>();
		}

		public void EditValue(Key key, Value oldValue, Value newValue)
		{
			lock (syncLock)
			{
				if (m_dictionary.ContainsKey(key))
				{
					if (m_dictionary[key].Contains(oldValue))
					{
						for (int i = 0; i < m_dictionary[key].Count; i++)
						{
							if (m_dictionary[key][i].Equals(oldValue))
							{
								m_dictionary[key][i] = newValue;
								break;
							}
						}
					}
				}
			}
		}

		public void ClearValues(Key key)
		{
			lock (syncLock)
			{
				if (m_dictionary.ContainsKey(key))
				{
					m_dictionary[key].Clear();
				}
			}
		}

		public IEnumerator<KeyValuePair<Key, List<Value>>> GetEnumerator()
		{
			return m_dictionary.GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return m_dictionary.GetEnumerator();
		}
	}
}
